package spaceinvaders;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class FilePlayer implements Runnable { 
	File file;
	AudioInputStream in;
	SourceDataLine line;
	int frameSize;
	byte[] buffer = new byte [32 * 1024];
	Thread playThread;
	boolean playing;
	boolean notYetEOF;

	public FilePlayer (File f)
			throws IOException,
			UnsupportedAudioFileException,
			LineUnavailableException {
		file = f;
		in = AudioSystem.getAudioInputStream (f);
		AudioFormat format = in.getFormat();
		frameSize = format.getFrameSize(); 
		DataLine.Info info = new DataLine.Info (SourceDataLine.class, format); 

		line = (SourceDataLine) AudioSystem.getLine (info); 

		line.open(); 

		playThread = new Thread (this); 
		playing = false; 
		notYetEOF = true;        
		playThread.start();
	}
	public void run() {
		int readPoint = 0;
		int bytesRead = 0;

		try {
			while (notYetEOF) {
				if (playing) {
					bytesRead = in.read (buffer, 
							readPoint, 
							buffer.length - readPoint);
					if (bytesRead == -1) { 
						notYetEOF = false; 
						break;
					}
					int leftover = bytesRead % frameSize;

					line.write (buffer, readPoint, bytesRead-leftover);

					System.arraycopy (buffer, bytesRead, buffer, 0,	leftover); 
					readPoint = leftover;
				} else {
					try {
						Thread.sleep (10);
					} 
					catch (InterruptedException ie) {}
				}
			}
			line.drain();
			line.stop();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		} finally {}
	}

	public void start() {
		playing = true;
		if (!playThread.isAlive())
			playThread.start();
		line.start();
	}

	public void stop() {
		playing = false;
		line.stop();
	}

	public SourceDataLine getLine() {
		return line;
	}

	public File getFile() {		
		return file; 
	} 
}